package cs342.project1.mathNotebook.xml;

import java.io.*;
import java.util.List;
import java.util.ArrayList;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import cs342.project1.mathNotebook.notebook.NotebookEntry;
import cs342.project1.mathNotebook.data.Parser;

/**
 * Provides the ability to read notebook entries from a data source
 * @author Jared Schlicht
 * @author Gabrielle DuBois
 */
public abstract class NotebookReader {
	protected InputStream in;

	/**
     * Constructor
     * @param inStream a ByteArrayInputStream which will be containing info
     */
    public NotebookReader(InputStream inStream){
		in = inStream;
    }//constructor

    /**
     * Loads data from specified file into a NotebookEntry List data structure
     * @param fileName a String denoting the file to be read from
     * @return list of notebook entries
     */
    public List<NotebookEntry> loadFile(String fileName){
		//take inputstream and translate into notebook data structure
		if (fileName != null){
			try{
				in = new FileInputStream(fileName);
			} catch (IOException e ) {}
		}//if(fileName == null)

		in = this.loadStream( in );

		List<NotebookEntry> results = new ArrayList<NotebookEntry>();
		NotebookEntry entry = null;

		Parser parser = new Parser();

		XMLInputFactory factory = XMLInputFactory.newInstance();
		try {
			XMLStreamReader reader = factory.createXMLStreamReader(in);
			while (reader.hasNext()) {
				int eventType = reader.getEventType();
				switch (eventType) {
				case XMLStreamConstants.START_ELEMENT:
					if (reader.getLocalName().equals("formula")) {
						entry = new NotebookEntry();
						int attributeCount = reader.getAttributeCount();
						for (int i = 0; i < attributeCount; i++) {
							if (reader.getAttributeLocalName(i).equals("equation")) {
								entry.functionString = reader.getAttributeValue(i);
								try {
									entry.function = parser.getExpression(entry.functionString);
								} catch (Exception e) {}
							}
						}
						results.add(entry);
					} else if (reader.getLocalName().equals("tangent")) {
					    int attributeCount = reader.getAttributeCount();
					    for (int i=0; i < attributeCount; i++) {
							if (reader.getAttributeLocalName(i).equals("point")) {
								entry.tangentPoints.add(Double.parseDouble(reader.getAttributeValue(i)));
							}
					    }
					}
					break;
				}

				reader.next();
			}
		} catch (XMLStreamException e) {
			// Present the user with an empty file in case of errors
		}

		return results;
    }//loadFile()


    /**
     * Gets data from a file and converts it into an InputStream for processing
     * @param fileName a String denoting the file to be loaded
     * @return An InputStream object containing the data from the file
     */
    public abstract InputStream loadStream(InputStream instream);


    /**
     * Closes any resources held by this NotebookReader
     */
    public void close() {
	    try {
			this.in.close();
	    }  catch (IOException e) {
			System.out.println("NotebookReader.close() error: " + e);
		}//tryCatch
	}//close()
}
